package com.qicheng.wlhyspider.hainan.conroller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.qicheng.wlhyspider.common.HttpUtils;
import com.qicheng.wlhyspider.common.PageResult;
import com.qicheng.wlhyspider.common.RedisUtils;
import com.qicheng.wlhyspider.common.Result;
import com.qicheng.wlhyspider.hainan.conroller.dto.ShippingNoteDTO;
import com.qicheng.wlhyspider.hainan.dao.ShippingNoteDriversRepository;
import com.qicheng.wlhyspider.hainan.dao.ShippingNoteGoodsRepository;
import com.qicheng.wlhyspider.hainan.dao.ShippingNoteMasterRepository;
import com.qicheng.wlhyspider.hainan.entity.ShippingNoteDriversEntity;
import com.qicheng.wlhyspider.hainan.entity.ShippingNoteGoodsEntity;
import com.qicheng.wlhyspider.hainan.entity.ShippingNoteMasterEntity;
import com.qicheng.wlhyspider.hainan.mapper.ShippingNoteDriversMapper;
import com.qicheng.wlhyspider.hainan.mapper.ShippingNoteGoodsMapper;
import com.qicheng.wlhyspider.hainan.mapper.ShippingNoteMasterMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/hainan/shipping")
@Slf4j
public class ShippingNoteController {
    private final ShippingNoteMasterRepository shippingNoteMasterRepository;
    private final ShippingNoteGoodsRepository shippingNoteGoodsRepository;
    private final ShippingNoteDriversRepository shippingNoteDriversRepository;
    private final RedisUtils redisUtils;
    private final ShippingNoteMasterMapper shippingNoteMasterMapper;
    private final ShippingNoteGoodsMapper shippingNoteGoodsMapper;
    private final ShippingNoteDriversMapper shippingNoteDriversMapper;


    public ShippingNoteController(ShippingNoteMasterRepository shippingNoteMasterRepository, ShippingNoteGoodsRepository shippingNoteGoodsRepository, ShippingNoteDriversRepository shippingNoteDriversRepository, RedisUtils redisUtils, ShippingNoteMasterMapper shippingNoteMasterMapper, ShippingNoteGoodsMapper shippingNoteGoodsMapper, ShippingNoteDriversMapper shippingNoteDriversMapper) {
        this.shippingNoteMasterRepository = shippingNoteMasterRepository;
        this.shippingNoteGoodsRepository = shippingNoteGoodsRepository;
        this.shippingNoteDriversRepository = shippingNoteDriversRepository;
        this.redisUtils = redisUtils;
        this.shippingNoteMasterMapper = shippingNoteMasterMapper;
        this.shippingNoteGoodsMapper = shippingNoteGoodsMapper;
        this.shippingNoteDriversMapper = shippingNoteDriversMapper;
    }

    private List<String> shippingIdList = new ArrayList<>();

//    @PostConstruct
//    public void getToken() {
//        log.info("================getToken======================");
//        LoginUtils.login(redisUtils);
//    }
//
//
//    @Scheduled(cron = "0 0/25 * * * ?")
//    public void refreshToken() {
//        log.info("================refreshToken======================");
//        LoginUtils.login(redisUtils);
//    }

    @GetMapping("/saveAll")
    public String saveAll(@RequestParam("page") Integer page,@RequestParam("maxPage") Integer maxPage) {
        if (CollectionUtil.isEmpty(shippingIdList)){
            shippingIdList =  shippingNoteMasterMapper.selectList(Wrappers.<ShippingNoteMasterEntity>lambdaQuery()
                    .select(ShippingNoteMasterEntity::getId)).stream().map(ShippingNoteMasterEntity::getId).collect(Collectors.toList());
        }
        Integer limit = 2000;
        Integer pages = 32;
//        LoginUtils.login();
        CompletableFuture<Object>[] futures = new CompletableFuture[pages];
        for (int i = 0; i < pages; i++) {
            int finalPage = page + i;
            CompletableFuture<Object> future = CompletableFuture.supplyAsync(() -> {
                try {
                    saveAllPri(finalPage, limit, "2021-01-01", "2021-01-31");
                    log.info("运单插入，第{}页成功", finalPage);
                } catch (Exception e) {
                    log.error("运单插入，第{}页失败", finalPage);
                    log.error(e.getMessage(), e);
                    e.printStackTrace();
                }
                return null;
            });
            futures[i] = future;
        }
        // todo 最好在循环插入的时候也捕获异常
        log.info("====futures.length=={}",futures.length);
        CompletableFuture<Void> cf = CompletableFuture.allOf(futures);

        // 如果执行成功:
        cf.thenAccept((result) -> {
            log.info("运单插入成功！！！");
            if (page < maxPage){
                saveAll(page + pages,maxPage);
            }

        });
        // 如果执行异常:
        cf.exceptionally((e) -> {
            e.printStackTrace();
            log.info("运单插入失败！！！");
            return null;
        });
        // 主线程不要立刻结束，否则CompletableFuture默认使用的线程池会立刻关闭:
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }



        return "运单插入成功！！！";
    }

//    @GetMapping("/save")
//    public String save(@RequestParam("page") Integer page, @RequestParam("limit") Integer limit, @RequestParam("startDate") String startDate, @RequestParam("endDate") String endDate) {
//        return saveAll(page, limit, startDate, endDate);
//    }

    private String saveAllPri(Integer page, Integer limit, String startDate, String endDate) {
        log.info("开始查询第{}页", page);
        String listUrl = String.format("http://wlhy.mot.gov.cn/hainan/business/shipping/list?page=%s&limit=%s",
                page, limit, startDate, endDate);
//        String listUrl = String.format("http://wlhy.mot.gov.cn/hainan/business/shipping/list?page=%s&limit=%s&sendToProDateTimeRange=%s+~+%s",
//                page, limit, startDate, endDate);
        HttpResponse httpResponse = HttpUtils.httpGet(listUrl,redisUtils);
        log.info("开始查询第{}页，返回状态{}", page, httpResponse.getStatus());
        if (httpResponse.getStatus() == 200) {
            String body = httpResponse.body();
            PageResult pageResult = JSONObject.parseObject(JSONObject.toJSONString(JSONObject.parse(body)), PageResult.class);
            PageResult.ResultDTO result = pageResult.getResult();
            List<ShippingNoteMasterEntity> list = JSONArray.parseArray(JSONArray.toJSONString(result.getRecords()), ShippingNoteMasterEntity.class);

            List<ShippingNoteMasterEntity> shippingNoteMasters = new ArrayList<>();
            List<ShippingNoteGoodsEntity> shippingNoteGoods = new ArrayList<>();
            List<ShippingNoteDriversEntity> shippingNoteDrivers = new ArrayList<>();
            String detailUrl = "http://wlhy.mot.gov.cn/hainan/business/shipping/id?id=%s";

            list = list.stream().filter(i -> !shippingIdList.contains(i.getId())).collect(Collectors.toList());
            for (ShippingNoteMasterEntity shipping : list) {
                String returnStr = saveDetail(shippingNoteMasters, shippingNoteGoods, shippingNoteDrivers, detailUrl, shipping);
                if (returnStr != null) return returnStr;
            }
            if (CollectionUtils.isNotEmpty(shippingNoteMasters)){
                shippingNoteMasterMapper.insertBatchSomeColumn(shippingNoteMasters);
//                for (ShippingNoteMasterEntity shippingNoteMaster : shippingNoteMasters) {
//                    shippingNoteMasterMapper.insert(shippingNoteMaster);
//                }
            }
            if (CollectionUtils.isNotEmpty(shippingNoteDrivers)){
                shippingNoteDriversMapper.insertBatchSomeColumn(shippingNoteDrivers);
//                for (ShippingNoteDriversEntity shippingNoteDriver : shippingNoteDrivers) {
//                    shippingNoteDriversMapper.insert(shippingNoteDriver);
//                }
            }
            if (CollectionUtils.isNotEmpty(shippingNoteGoods)){
                shippingNoteGoodsMapper.insertBatchSomeColumn(shippingNoteGoods);
//                for (ShippingNoteGoodsEntity shippingNoteGood : shippingNoteGoods) {
//                    shippingNoteGoodsMapper.insert(shippingNoteGood);
//                }
            }
            log.info(String.format("运单查询，%s到%s，第%s页，总页数%s", startDate, endDate, page, result.getPages()));
//            if (page < result.getPages()) {
//                page++;
//                return save(page, limit, startDate, endDate);
//            }

        } else if (httpResponse.getStatus() == 203) {
            log.info("登录信息失效");
//            return "返回：登录信息失效";
//            LoginUtils.login();
            return saveAllPri(page, limit, startDate, endDate);
        } else {
            log.info("查询失败");
            return "返回：查询失败";
        }
        log.info("返回：插入成功");
        return "插入成功";
    }

    private String saveDetail(List<ShippingNoteMasterEntity> shippingNoteMasters, List<ShippingNoteGoodsEntity> shippingNoteGoods,
                              List<ShippingNoteDriversEntity> shippingNoteDrivers, String detailUrl, ShippingNoteMasterEntity shipping) {
        log.info("获取运单详情，id={}", shipping.getId());
        HttpResponse httpResponse = HttpUtils.httpGet(String.format(detailUrl, shipping.getId()),redisUtils);
        if (httpResponse.getStatus() == 200) {
            String detailBody = httpResponse.body();
            Result detailResult = JSONObject.parseObject(JSONObject.toJSONString(JSONObject.parse(detailBody)), Result.class);
            ShippingNoteDTO shippingNoteDTO = JSONObject.parseObject(JSONObject.toJSONString(detailResult.getResult()), ShippingNoteDTO.class);
            shippingNoteMasters.add(shippingNoteDTO.getShippingNoteMaster());
            if (CollectionUtil.isNotEmpty(shippingNoteDTO.getShippingNoteGoods())) {
                shippingNoteGoods.addAll(shippingNoteDTO.getShippingNoteGoods());
            }
            if (CollectionUtil.isNotEmpty(shippingNoteDTO.getShippingNoteDrivers())) {
                shippingNoteDrivers.addAll(shippingNoteDTO.getShippingNoteDrivers());
            }
        } else if (httpResponse.getStatus() == 203) {
            log.info("登录信息失效");
//                    return "登录信息失效";
//            LoginUtils.login();
            return saveDetail(shippingNoteMasters, shippingNoteGoods, shippingNoteDrivers, detailUrl, shipping);
        } else {
            log.info("查询失败");
            return "查询失败";
        }
        return null;
    }

}
